package com.zhoulz.homework.chaptor02;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.CuratorWatcher;
import org.apache.curator.utils.CloseableUtils;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;

import com.zhoulz.homework.chaptor02.config.Command;
import com.zhoulz.homework.chaptor02.config.Config;
import com.zhoulz.homework.chaptor02.zk.Zk;

/**
 * 命令控制台
 * @author zhoulz
 *
 */
public class Cmd {
	static CuratorFramework client = null;
	public static void main(String[] args) throws Exception {
		try {
			Config.load(Config.LOCAL_CONFIG_NAME);
			client = Zk.newClient(String.format("%s:%s", 
					Config.get(Config.KEY_ZK_SERVER_IP), 
					Config.get(Config.KEY_ZK_SERVER_PORT)));
			client.start();
			if(client.getZookeeperClient().blockUntilConnectedOrTimedOut()){
				Zk.init(client);
				
				printHelp();
				BufferedReader  in = new BufferedReader(new InputStreamReader(System.in));
				boolean         done = false;
				while ( !done ){
					System.out.print(" > ");
					String      line = in.readLine();
					if ( line == null ){
						break;
					}
					
					String      command = line.trim();
					String[]    parts = command.split("\\s");
					if ( parts.length == 0 )
					{
						continue;
					}
					String      operation = parts[0];
					String      cmdArgs[] = Arrays.copyOfRange(parts, 1, parts.length);
					
					if ( operation.equalsIgnoreCase("q") || operation.equalsIgnoreCase("quit") )
					{
						done = true;
					}
					else if ( operation.equals("list") )
					{
						list(command, cmdArgs);
					}
					else if ( operation.equals("shutdown") )
					{
						shutdown(command, cmdArgs);
					}else{
						printHelp();
					}
				}
			}else{
				System.err.println("connet to zookeeper fail, please set config/zookeeper.properties");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			CloseableUtils.closeQuietly(client);
		}
		for (int i = 5; i > 0; i--) {
			System.out.println(i);
			Thread.sleep(1000);
		}
		System.exit(0);
	}
	private static void doCommand(String cmdNodePath, byte[] cmdNodeData)
			throws Exception {
		if(Zk.existsBuilder.forPath(cmdNodePath) == null){
			Zk.createBuilder.withMode(CreateMode.EPHEMERAL).forPath(cmdNodePath, cmdNodeData);
		}else{
			Zk.setDataBuilder.forPath(cmdNodePath, cmdNodeData);
		}
		Zk.getDateBuilder.usingWatcher(new CuratorWatcher() {
			
			public void process(WatchedEvent event) throws Exception {
				switch (event.getType()) {
				case NodeDataChanged:
					System.out.println(new String(Zk.getDateBuilder.forPath(event.getPath()), Config.ENCODING));
					break;

				default:
					break;
				}
			}
		}).forPath(cmdNodePath);
	}
    private static void list(String command, String[] cmdArgs) {
    	try {
			if(cmdArgs.length == 0){
				List<String> nodes = Zk.getChildrenBuilder.forPath(Zk.APP_NODE_PATH);
				System.out.println("All Nodes:");
				for (String node : nodes) {
					System.out.println(node);
				}
			}else if(cmdArgs[0].equals("files")){
				
				String cmdNodePath = String.format("%s/%s-%s", Zk.APP_COMMANDS_PATH, Zk.APP_COMMANDS, cmdArgs[1]);
				byte[] cmdNodeData = Command.LSIT_FILE.getBytes();
				
				doCommand(cmdNodePath, cmdNodeData);
			}
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
	}
	private static void shutdown(String command, String[] cmdArgs) {
		try {
			if(cmdArgs.length == 0){
				List<String> nodes = Zk.getChildrenBuilder.forPath(Zk.APP_NODE_PATH);
				System.out.println("All Nodes:");
				for (String node : nodes) {
					shutdown(command, new String[]{node});
				}
			}else{
				final String cmdNodePath = String.format("%s/%s-%s", Zk.APP_COMMANDS_PATH, Zk.APP_COMMANDS, cmdArgs[0]);
				byte[] cmdNodeData = Command.SHUTDOWN.getBytes();
				doCommand(cmdNodePath, cmdNodeData);
				new Timer(true).schedule(new TimerTask() {
					
					@Override
					public void run() {
						try {
							Zk.deleteBuilder.guaranteed().forPath(cmdNodePath);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}, 3 * 1000);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private static void printHelp()
    {
    	System.out.println("#####################################################");
        System.out.println(" 欢迎使用节点控制台，通过使用下面命令来操作节点:\n");
        System.out.println(" list: 列出所有节点");
        System.out.println(" list files <nodeName>: 列出指定节点接收到的10个文件");
        System.out.println(" shutdown: 安全停止所有节点");
        System.out.println(" shutdown <nodeName>: 安全停止指定节点");
        System.out.println(" quit: 退出");
        System.out.println("#####################################################");
    }
}
